package com.example.edu.ast;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.PackageDeclaration;
import com.github.javaparser.ast.body.BodyDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.BinaryExpr;
import com.github.javaparser.ast.expr.SimpleName;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.ReferenceType;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

import java.util.List;
import java.util.Optional;

public class ASTMain {

    public static void main(String[] args) {
        final MethodDeclaration methodDeclaration = StaticJavaParser.parseMethodDeclaration("public PageVO<DependencyVO> getPage(DependencyQuery getPageQuery) {\n" +
                "        if (getPageQuery == null) {\n" +
                "            return null;\n" +
                "        } else if (getPageQuery != null) {\n" +
                "\n" +
                "        } else {\n" +
                "\n" +
                "        }\n" +
                "\n" +
                "        object = new Object();\n" +
                "\n" +
                "        Page<Dependency> page = new Page(getPageQuery.getPageNum(), getPageQuery.getPageSize());\n" +
                "\n" +
                "        QueryWrapper<Dependency> queryWrapper = getQueryWrapper(getPageQuery);\n" +
                "        List<DependencyVO> dependencyVOS = new ArrayList<>();\n" +
                "\n" +
                "        Page<Dependency> starterDepPage = dependencyDao.selectPage(page, queryWrapper);\n" +
                "        List<Dependency> records = starterDepPage.getRecords();\n" +
                "        if (records != null && !records.isEmpty()) {\n" +
                "            dependencyVOS = covert(records);\n" +
                "        }\n" +
                "        return PageVO.getInstance(getPageQuery.getPageNum(), getPageQuery.getPageSize(), dependencyVOS, (int) starterDepPage.getTotal());\n" +
                "    }");

        new VoidVisitorAdapter() {
            @Override
            public void visit(MethodDeclaration n, Object arg) {
                super.visit(n, arg);
                System.out.println(n.getClass() + "====" + n + "====" + n.getRange());
            }

            @Override
            public void visit(BinaryExpr n, Object arg) {
                super.visit(n, arg);
                System.out.println(n.getClass() + "====" + n + "====" + n.getRange());
            }
        }.visit(methodDeclaration, null);
        System.out.println();
    }

    private static void test() {
        CompilationUnit parse = parse();
        // package
        Optional<PackageDeclaration> packageDeclaration = parse.getPackageDeclaration();
        // import
        NodeList<ImportDeclaration> imports = parse.getImports();
        // class
        NodeList<TypeDeclaration<?>> types = parse.getTypes();
        TypeDeclaration<?> typeDeclaration = types.get(0);
        if (typeDeclaration instanceof ClassOrInterfaceDeclaration) {
            ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration) typeDeclaration;
            // 注释，只取出最后一个注释
            final Optional<Comment> comment = classOrInterfaceDeclaration.getComment();
            // 注解
            final NodeList<AnnotationExpr> annotations = classOrInterfaceDeclaration.getAnnotations();
            final Optional<AnnotationExpr> service = classOrInterfaceDeclaration.getAnnotationByName("Service");
            // 类修饰符
            final NodeList<Modifier> modifiers = classOrInterfaceDeclaration.getModifiers();
            // 是否接口
            final boolean anInterface = classOrInterfaceDeclaration.isInterface();
            // 继承
            final NodeList<ClassOrInterfaceType> extendedTypes = classOrInterfaceDeclaration.getExtendedTypes();
            // 实现
            final NodeList<ClassOrInterfaceType> implementedTypes = classOrInterfaceDeclaration.getImplementedTypes();
            // 类名
            final SimpleName name = classOrInterfaceDeclaration.getName();
            // 属性 + 方法
            final NodeList<BodyDeclaration<?>> members = classOrInterfaceDeclaration.getMembers();
            // 属性
            final List<FieldDeclaration> fields = classOrInterfaceDeclaration.getFields();
            // 方法
            final List<MethodDeclaration> methods = classOrInterfaceDeclaration.getMethods();
            final MethodDeclaration methodDeclaration = methods.get(0);
            // 方法修饰符
            final NodeList<Modifier> methodModifier = methodDeclaration.getModifiers();
            // 方法返回值
            final Type type = methodDeclaration.getType();
            if (type instanceof ClassOrInterfaceType) {
                final ClassOrInterfaceType methodReturnType = (ClassOrInterfaceType) type;
            }
            // 方法参数
            final NodeList<Parameter> parameters = methodDeclaration.getParameters();
            // 方法异常
            final NodeList<ReferenceType> thrownExceptions = methodDeclaration.getThrownExceptions();
            // 方法体
            final BlockStmt blockStmt = methodDeclaration.getBody().get();
            if (blockStmt != null) {
            }

            new VisitorImpl().visit(parse, null);
            System.out.println();
        }
    }

    private static CompilationUnit parse() {
        final CompilationUnit parse = StaticJavaParser.parse(ASTMain.class.getClassLoader().getResourceAsStream("DependencyService.java"));
        return parse;
    }
}
